/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.sdk.metrics.view;

import com.google.auto.value.AutoValue;
import io.opentelemetry.sdk.metrics.internal.view.StringPredicates;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import javax.annotation.concurrent.Immutable;

/**
 * Provides means for selecting one or more Meters. Used for selecting instruments when constructing
 * views.
 */
@AutoValue
@Immutable
public abstract class MeterSelector {

  /**
   * Returns a new {@link Builder} for {@link InstrumentSelector}.
   *
   * @return a new {@link Builder} for {@link InstrumentSelector}.
   */
  public static Builder builder() {
    return new AutoValue_MeterSelector.Builder()
        .setNameFilter(StringPredicates.ALL)
        .setVersionFilter(StringPredicates.ALL)
        .setSchemaUrlFilter(StringPredicates.ALL);
  }

  /**
   * Returns the {@link Pattern} generated by the provided {@code regex} in the {@link Builder}, or
   * {@code Pattern.compile(".*")} if none was specified.
   */
  public abstract Predicate<String> getNameFilter();

  /**
   * Returns the {@link Pattern} generated by the provided {@code regex} in the {@link Builder}, or
   * {@code Pattern.compile(".*")} if none was specified.
   */
  public abstract Predicate<String> getVersionFilter();

  /**
   * Returns the {@link Pattern} generated by the provided {@code regex} in the {@link Builder}, or
   * {@code Pattern.compile(".*")} if none was specified.
   */
  public abstract Predicate<String> getSchemaUrlFilter();

  /** Builder for {@link InstrumentSelector} instances. */
  @AutoValue.Builder
  public abstract static class Builder {

    /**
     * Sets the {@link Predicate} for matching name.
     *
     * <p>Note: The last provided of {@link #setNameFilter}, {@link #setNamePattern} and {@link
     * #setName} is used.
     */
    public abstract Builder setNameFilter(Predicate<String> filter);

    /**
     * Sets the {@link Pattern} for matching name.
     *
     * <p>Note: The last provided of {@link #setNameFilter}, {@link #setNamePattern} and {@link
     * #setName} is used.
     */
    public final Builder setNamePattern(Pattern pattern) {
      return setNameFilter(StringPredicates.regex(pattern));
    }

    /**
     * Sets a specifier for selecting Instruments by name.
     *
     * <p>Note: The last provided of {@link #setNameFilter}, {@link #setNamePattern} and {@link
     * #setName} is used.
     */
    public final Builder setName(String name) {
      return setNameFilter(StringPredicates.exact(name));
    }

    /**
     * Sets the {@link Predicate} for matching versions.
     *
     * <p>Note: The last provided of {@link #setVersionFilter}, {@link #setVersionPattern} and
     * {@link #setVersion} is used.
     */
    public abstract Builder setVersionFilter(Predicate<String> filter);

    /**
     * Sets the {@link Pattern} for matching versions.
     *
     * <p>Note: The last provided of {@link #setVersionFilter}, {@link #setVersionPattern} and
     * {@link #setVersion} is used.
     */
    public final Builder setVersionPattern(Pattern pattern) {
      return setVersionFilter(StringPredicates.regex(pattern));
    }

    /**
     * Sets a specifier for selecting Meters by version.
     *
     * <p>Note: The last provided of {@link #setVersionFilter}, {@link #setVersionPattern} and
     * {@link #setVersion} is used.
     */
    public final Builder setVersion(String version) {
      return setVersionFilter(StringPredicates.exact(version));
    }

    /**
     * Sets the {@link Predicate} for matching schema urls.
     *
     * <p>Note: The last provided of {@link #setSchemaUrlFilter}, {@link #setSchemaUrlPattern} and
     * {@link #setSchemaUrl} is used.
     */
    abstract Builder setSchemaUrlFilter(Predicate<String> filter);

    /**
     * Sets the {@link Pattern} for matching schema urls.
     *
     * <p>Note: The last provided of {@link #setSchemaUrlFilter}, {@link #setSchemaUrlPattern} and
     * {@link #setSchemaUrl} is used.
     */
    public final Builder setSchemaUrlPattern(Pattern pattern) {
      return setSchemaUrlFilter(StringPredicates.regex(pattern));
    }

    /**
     * Sets the schema url to match.
     *
     * <p>Note: The last provided of {@link #setSchemaUrlFilter}, {@link #setSchemaUrlPattern} and
     * {@link #setSchemaUrl} is used.
     */
    public final Builder setSchemaUrl(String url) {
      return setSchemaUrlFilter(StringPredicates.exact(url));
    }

    /** Returns an InstrumentSelector instance with the content of this builder. */
    public abstract MeterSelector build();
  }
}
